/*
*日志宏的实现
*序列化与反序列化
*uuid的实现
*/

#pragma once

#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <random>
#include <sstream>
#include <atomic>
#include <iomanip>
#include <jsoncpp/json/json.h>

#define LDBG 0
#define LINF 1
#define LERR 2
#define LDEFAULT LDBG

#define Log(level,format,...) { \
    if (level >= LDEFAULT){\
            time_t t = time(NULL);\
            struct tm *lt = localtime(&t);\
            char time_tmp[32] = {0};\
            strftime(time_tmp, 31, "%m-%d %T", lt);\
            fprintf(stdout, "[%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
        }\
}

#define DLog(format,...)    Log(LDBG,format,##__VA_ARGS__);
#define ILog(format,...)    Log(LINF,format,##__VA_ARGS__);
#define ELog(format,...)    Log(LERR,format,##__VA_ARGS__);

namespace Util
{
    using namespace std;
    class JSON
    {
        public:
            static bool serialize(const Json::Value &val,  std::string &body) {
                std::stringstream ss;
                //先实例化一个工厂类对象
                Json::StreamWriterBuilder swb;
                //通过工厂类对象来生产派生类对象
                std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
                int ret = sw->write(val, &ss);
                if (ret != 0) {
                    ELog("json serialize failed!");
                    return false;
                }
                body = ss.str();
                return true;
            }

            static bool unserialize(const std::string &body, Json::Value &val) {
                Json::CharReaderBuilder crb;
                std::string errs;
                std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
                bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
                if (ret == false) {
                    ELog("json unserialize failed : %s", errs.c_str());
                    return false;
                }
                return true;
            }
    };
    class UUID
    {
        public:
        static string uuid()
        {
            stringstream ss;
            //1.构造一个机器随机数对象
            random_device rd;
            //2.以机器随机数为种子构造随机数对象
            mt19937 generator(rd());
            //3.构造随机数范围对象
            uniform_int_distribution<int> distribution(0,255);
            //4.生成8个随机数，按照特定格式组织成为16进制数组字符的字符串
            for(int i=0;i<8;i++)
            {
                if(i==4||i==6) ss<<'-';
                ss<<setw(2)<<setfill('0')<<hex<<distribution(generator);
            }
            ss<<'-';
            //5.定义一个8字节字节序号，逐字节组织成为16进制数字字符的字符串
            static atomic<size_t> seq(1);//为了都是同一个数进行操作
            size_t cur=seq.fetch_add(1);
            for (int i = 7; i >= 0; i--) //为了显示不是01而是10
            {
                if (i == 5) ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i*8)) & 0xFF); //取他的最低位
            }
            return ss.str();
        }
    };
}
